package com.loster.login.strategy;

import com.loster.login.config.LoginTypeConfig;
import jakarta.annotation.Resource;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 操作策略的上下文环境类 工具类
 * 整合策略，方便管理
 */
@Component
public class UserLoginFactory  implements ApplicationContextAware {
    /**
     * 线程安全：ConcurrentHashMap 是 Java 提供的线程安全的集合类，适用于多线程环境。
     * 在多线程环境中，ConcurrentHashMap 可以保证在多个线程同时访问时不会出现数据不一致的问题。
     */
    private static Map<String,UserGranter> getPool = new ConcurrentHashMap<>();

    @Resource
    private LoginTypeConfig loginTypeConfig;

    /**
     *从配置文件中读取策略信息存储到map中
     *
     * account:accountGranter,
     * sms:smsGranter,
     * we_chat:wechatGranter
     *
     * @ param applicationContext
     * @throws BeansException
     *
     */


    /**
     * setApplicationContext 方法：这个方法会在 Spring 容器启动时被调用，applicationContext 参数就是当前的应用上下文。
     * 使用 applicationContext：在 setApplicationContext 方法中，你可以使用 applicationContext 来获取 Spring 管理的 Bean。
     * 例如，你可以通过 applicationContext.getBean(beanName) 来获取一个 Bean 实例。
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        /**
         * applicationContext.getBean(value)：通过 ApplicationContext 获取指定名称的 Bean 实例。
         * value 是 Bean 的名称。
         */
        loginTypeConfig.getTypes().forEach((key,value)->{ // key键，value：值
            getPool.put(key,(UserGranter) applicationContext.getBean(value));
        });
    }

    /**
     *对外提供具体策略类
     * @param grantType 用户登录方式，需要跟 配置文件中匹配
     * @return 具体策略
     */
    public UserGranter getGranter(String grantType){
        return getPool.get(grantType);
    }
}
